package view;

import Enums.State;
//import com.sun.awt.AWTUtilities;
import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class WeightingDialog {

    private BufferedImage paint_on, maske, contImg, maskCont;
    private model.Model_Image_Original model;
    private Graphics2D g_maske, g_maskCont;
    private AlphaComposite alphaComposite = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f);
    private controller.Controller controller;
    private JSlider pinselkopf = new JSlider(1, 100, 5), pinselfarbe = new JSlider(1, 3, 3);
    private Color weight_color, color_cont;
    private JFrame parent;
    private JDialog dialog = new JDialog(parent);
    private JPanel panel, panel_pinsel;
//    private Cursor cursor_def = new Cursor(Cursor.DEFAULT_CURSOR);
    private int mouseX = 0, mouseY = 0;
    private Point mouseOnScreen;
    private boolean drawCursor = false;
    private int WIDTH, HEIGHT, TYPE;
    private JCheckBox check_maks = new JCheckBox("Maske"), check_cont = new JCheckBox("Kontrast"),
            cont_rise = new JCheckBox("verdunkeln", true), cont_fall = new JCheckBox("erhellen", false);
    private ButtonGroup check_gr = new ButtonGroup(), cont_gr = new ButtonGroup();
//    private Cursor cursor_cus = new Cursor(Cursor.)

    public WeightingDialog(final model.Model_Image_Original model, JFrame parent, controller.Controller controller) {
        this.model = model;
        this.parent = parent;
        this.controller = controller;
        check_maks.setSelected(true);
        check_gr.add(check_maks);
        check_gr.add(check_cont);

        cont_gr.add(cont_rise);
        cont_gr.add(cont_fall);
        paint_on = model.getImage_original();
        WIDTH = model.getImage_original().getWidth();
        HEIGHT = model.getImage_original().getHeight();
//                System.out.print("W: "+WIDTH);
//                System.out.println(" H: "+HEIGHT);
        TYPE = model.getImage_original().getType();
        contImg = new BufferedImage(WIDTH, HEIGHT, TYPE);
        maskCont = new BufferedImage(WIDTH, HEIGHT, TYPE);
        contImg.getGraphics().drawImage(paint_on, 0, 0, null);
        //paint_on = new BufferedImage(WIDTH, HEIGHT,TYPE);
        //paint_on.setAccelerationPriority(1);
        this.maske = new BufferedImage(WIDTH, HEIGHT, TYPE);
        g_maske = maske.createGraphics();
        g_maske.drawImage(model.getMaske(), 0,0, null);
        g_maskCont = maskCont.createGraphics();
        //g_maske.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f));
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                init();
            }
        });

        new javax.swing.Timer(50, new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                repaintpanel();
            }
        }).start();
    }

    private void init() {
        dialog.setUndecorated(true);
        dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
        dialog.setTitle("Gewichtung vornehmen");
        dialog.setLayout(new BorderLayout());
        JButton button = new JButton("fertig"), abbrechen = new JButton("Abbrechen");

        check_maks.addChangeListener(new ChangeListener() {

            public void stateChanged(ChangeEvent e) {
                //pinselfarbe.
            }
        });
        button.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                try {
                    done();
                } catch (Exception ex) {
                    controller.setState(State.waiting);
                    JOptionPane.showMessageDialog(null, "Fehler beim Erstellen\n" + ex  , "ERROR", JOptionPane.ERROR_MESSAGE);
                    //Logger.getLogger(WeightingDialog.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        abbrechen.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                close();
            }
        });
        panel = new JPanel() {

            @Override
            public Dimension getPreferredSize() {
//                System.out.println("panel size");
                return new Dimension(model.getWidth(), model.getHeight());
            }

            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                if (check_maks.isSelected()) {
                    pinselfarbe.setEnabled(true);
                    cont_rise.setEnabled(false);
                    cont_fall.setEnabled(false);
                    g2.drawImage(paint_on, 0, 0, null);
                    g2.setComposite(alphaComposite);
                    g.drawImage(maske, 0, 0, null);
                } else if (check_cont.isSelected()) {
                    cont_rise.setEnabled(true);
                    cont_fall.setEnabled(true);
                    pinselfarbe.setEnabled(false);
//                    g2.drawImage(maskCont, 0, 0, null);
                    g2.drawImage(contImg, 0, 0, null);
                }
                if (drawCursor) {
                    int p = pinselkopf.getValue();
                    g.setColor(Color.red);
                    if(!check_cont.isSelected()){
                        g.drawOval(mouseX - p / 2, mouseY - p / 2, p, p);
                    }
                    else{
                        g.drawRect(mouseX - p / 2, mouseY - p / 2, p, p);
                    }
                }
            }
        };
        panel.addMouseListener(new MouseListener() {

            public void mouseClicked(MouseEvent e) {
                mouseX = e.getX();
                mouseY = e.getY();
                mouseOnScreen = e.getLocationOnScreen();
                if (check_maks.isSelected()) {
                    mask();
                } else if (check_cont.isSelected()) {
                    cont();
                }
            }

            public void mousePressed(MouseEvent e) {
            }

            public void mouseReleased(MouseEvent e) {
            }

            public void mouseEntered(MouseEvent e) {
                drawCursor = true;
            }

            public void mouseExited(MouseEvent e) {
                drawCursor = false;
            }
        });

        panel.addMouseMotionListener(new MouseMotionListener() {

            public void mouseDragged(MouseEvent e) {
                mouseX = e.getX();
                mouseY = e.getY();
                mouseOnScreen = e.getLocationOnScreen();
                if (check_maks.isSelected()) {
                    mask();
                } else if (check_cont.isSelected()) {
                    cont();
                }
            }

            public void mouseMoved(MouseEvent e) {
                mouseX = e.getX();
                mouseY = e.getY();
                mouseOnScreen = e.getLocationOnScreen();
            }
        });
//        JScrollPane pane = new JScrollPane(panel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED) {
//
//            @Override
//            public Dimension getPreferredSize() {
//                int w_75 = (int) (parent.getSize().getWidth() * 0.75);
//                int h_75 = (int) (parent.getSize().getHeight() * 0.75);
//                int w = w_75 > model.getWidth() ? model.getHeight() + 5 : w_75,
//                        h = h_75 > model.getHeight() ? model.getHeight() + 5 : h_75;
//                return new Dimension(w, h);
//            }
//        };

        panel_pinsel = new JPanel() {

            @Override
            public Dimension getPreferredSize() {
                return new Dimension((int) (parent.getWidth() * 0.2), -1);
            }
        };
        panel_pinsel.setLayout(new GridLayout(8, 2));
        pinselkopf.setToolTipText("Pinselgröße");
        panel_pinsel.add(pinselkopf);
        pinselfarbe.setToolTipText("die Farbe des Pinsel");
        panel_pinsel.add(pinselfarbe);
        panel_pinsel.add(check_maks);
        panel_pinsel.add(check_cont);
        JPanel p = new JPanel(new GridLayout(1, 2));
        p.add(cont_rise);
        p.add(cont_fall);
        cont_rise.setToolTipText("Bildbereich verdunkeln");
        cont_fall.setToolTipText("Bildbereich erhellen");
        panel_pinsel.add(p);
        dialog.add(panel_pinsel, BorderLayout.WEST);
        //dialog.add(pane, BorderLayout.CENTER);
        dialog.add(panel);
        JPanel p2 = new JPanel(new GridLayout(1, 2));
        p2.add(button);
        p2.add(abbrechen);
        dialog.add(p2, BorderLayout.SOUTH);
        dialog.pack();
        dialog.setLocationRelativeTo(parent);
        dialog.setModal(true);
//        AWTUtilities.setWindowOpacity(parent, 0.3f);
        dialog.setVisible(true);
    }

    private void mask() {
        int pinsel = pinselkopf.getValue();
        switch (pinselfarbe.getValue()) {
            case 3:
                weight_color = Color.WHITE;
                break;
            case 2:
                weight_color = Color.GRAY;
                break;
            case 1:
                weight_color = Color.BLACK;
                break;
        }
        g_maske.setColor(weight_color);
        g_maske.fillOval(mouseX - pinsel / 2, mouseY - pinsel / 2, pinsel, pinsel);
    }
    private int[] a = null;

    private void cont(){
        int pinsel = pinselkopf.getValue();
        int x = (mouseX - pinsel/2) % WIDTH;
        int y = (mouseY - pinsel/2) % HEIGHT;

        Rectangle rect = new Rectangle(x, y, pinsel, pinsel);
        
        if(rect.x < 0){
            rect.width = pinsel + x;
            rect.x = 0;
        }
        else if(rect.x+rect.width > WIDTH){
            rect.width = rect.width - (rect.x+rect.width - WIDTH);
        }

        if(rect.y < 0){
            rect.height = pinsel + y;
            rect.y = 0;
        }
        else if(rect.y + rect.height > HEIGHT){
            rect.height = rect.height - (rect.y + rect.height - HEIGHT);
        }
       
        if(rect.width <=0 ){return;}
        if(rect.height<=0){return;}

//        System.out.println(rect);
        Raster raster = contImg.getData(rect);
        WritableRaster wr= raster.createCompatibleWritableRaster(rect);

        int[] px = raster.getPixels(rect.x, rect.y, rect.width, rect.height, a);
        for(int i=0; i<px.length; i++){
            if(cont_rise.isSelected()){
                px[i] -=1;
                if(px[i] < 0) px[i] = 0;
            }
            else if(cont_fall.isSelected()) {
                px[i] +=1;
                if(px[i] > 255){
                    px[i] = 255;
                }
            }
        }
        wr.setPixels(rect.x, rect.y, rect.width, rect.height, px);
        contImg.setData(wr);
    }

    // sobald der user fertig ist, werden die gewichtungen  zurückgegeben
    private void done() throws Exception {
        try {
            model.setImage_original(contImg);
            controller.setLogMessage("Kontrast geändert\n");
            model.setMaske(maske);
            model.create_grayValuematrixMaske();
            controller.setLogMessage("Maske erstellt\n");
            close();
        } catch (Exception ex) {
            throw new Exception(ex.toString());
        }
    }

    private void close() {
//        AWTUtilities.setWindowOpacity(parent, 1.0f);
        dialog.dispose();
    }

    private void repaintpanel() {
        panel.repaint();
    }
}
